from django.shortcuts import render
from rest_framework import viewsets
from .models import Card, Order
from .serializers import CardSerializer, OrderSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAdminUser,IsAuthenticated,SAFE_METHODS
from utils.errors import TradeError, UserError
from utils.common import get_random_code
from utils.alipayy import AliPay
from django.utils import timezone
from datetime import timedelta
from account.models import Profile
from .permissions import IsAdminUserOrReadOnly
from django.conf import settings
from django.db import transaction
from utils.filters import OrderFilter


# Create your views here.
class CardViewSet(viewsets.ModelViewSet):
    queryset = Card.objects.all()
    serializer_class = CardSerializer
    permission_classes = [IsAdminUserOrReadOnly]


class AlipayAPIView(APIView):
    def get(self, request):
        """
        发起支付宝支付,有2种场景
        1.创建新支付
        2.支付未完成的订单
        """
        # 检测卡号id是否正确
        card_id = request.GET.get("card_id" , None)
        card = Card.objects.get(id=card_id)
        
        if not card:
            return Response(*TradeError.CardParamError)
        # 判断订单号是否存在，存在则表示执行之前未支付的订单
        # 否则，支付新订单
        order_sn = request.GET.get("order_sn" , None)

        if not order_sn:
            # 生成新的订单号
            out_trade_no = "pay" + timezone.now().strftime("%Y%m%d%H%M%S") + get_random_code(4)

            try:
      
                # 生成订单
                # uid = request.session.get('uid')
                # uid = 'KDMq56nRWJL6jWUhLyQ7SC'
                print(request.user)
                Order.objects.create(
                    user = Profile.objects.get(user = request.user),
                    order_sn = out_trade_no,
                    order_mount = card.card_price,
                    card = card,
                    pay_time = timezone.now()
                )
                
            except Exception as e:
                print(e)
        else:
            try:
                order = Order.objects.get(order_sn = order_sn)
                if order.pay_status != 'PAYING':
                    return Response(*TradeError.OrderStatusError)
                out_trade_no = order.order_sn
            except Exception as e:
                return Response(*TradeError.OrderStatusError)

        try:
            alipay = AliPay()
            url = alipay.trade_page(out_trade_no, str(card.card_price), card.card_name, "支付宝测试", "FAST_INSTANT_TRADE_PAY")
            # return Response({"url": url})
            return Response(url)
        except Exception as e:
            print(e)
            return Response('支付失败')


class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer
    filterset_class =  OrderFilter
    
    def get_permissions(self):
        if self.request.method in SAFE_METHODS:
            return [IsAuthenticated()]
        else:
            return [IsAdminUser()]
    
    def list(self, request):
        user = request.user
        profile = Profile.objects.get(user=user)
        order = Order.objects.filter(user_id = profile.uid).order_by("-created_at")
        serializer = OrderSerializer(order, many=True)
  
        return Response(serializer.data)
    
    
    
class AlipayCallbackAPIView(APIView):
    def post(self,request):
        params = request.POST.dict()
        sign = params.pop('sign')
        del params['sign_type']
        
        # 对字典进行排序
        sorted_list = sorted([(k,v) for k,v in params.items()])
        unsigned_string = '&'.join(f"{k}={v}" for k,v in sorted_list)
        alipay = AliPay()
        if not alipay.verify(unsigned_string,sign):
            print("失败")
            return Response("error")
        # 验证order
        try:
            order = Order.objects.get(order_sn = params.get('out_trade_no'))
        except:
            print("失败")
            return Response("error")
        
        # 验证订单金额
        if params.get("total_amount")  != str(order.order_mount):
            print("订单金额失败")
            return Response("error")
        
        # 验证seller_id
        if params.get('seller_id') != settings.ALIPAY_SELLER_ID:
            print("seller_id失败")
            return Response("error")
        
        if params.get("app_id") != settings.ALIPAY_APP_ID:
            print("app_id失败")
            return Response("error")
        
        if params.get("trade_status") not in ["TRADE_SUCCESS","TRADE_FINISHED"]:
            print("trade_status失败")
            return Response("error")
        
        # 业务逻辑
        # 更改order表
        # 使用事务保持一致性，必须同时修改
        with transaction.atomic():

            order.trade_no = params.get("trade_no")
            order.pay_status = params.get("trade_status")
            order.pay_time = timezone.now()
            order.save()

            # 更改profile表

            profile = Profile.objects.get(uid = order.user.uid)
            profile.is_upgrade = 1
            profile.upgrade_time = timezone.now()
            profile.upgrade_count +=1
            # 如果用户首次充值或者会员已经过期，那么设置过期时常应为当前时间+会员卡时长
            # 如果未过期，需要在原来的实践基础上再加上会员卡时长
            if not profile.expire_time or profile.expire_time < timezone.now(): 
                profile.expire_time = timezone.now() + timedelta(days=order.card.duration)
            else:
                profile.expire_time = profile.expire_time + timedelta(days=order.card.duration)
            profile.save()

        return Response("success")
    
    
from .tasks import add,mul,xsum
class TaskAPIView(APIView):
    
    
    def get(self,request):
        result1 = add.delay(3,4)
        print(result1)
        result1 = mul.delay(3,4)
        print(result1)
        result1 = xsum.delay(4)
        print(result1)
        
        return Response("执行tasks")